//
//  BaseViewController.swift
//  Matting
//  Created by JoyWT on 2022/3/4
//  
    

import UIKit
import opencv2
import Vision
class BaseViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    var titleText = ""
    let img = UIImage(named: "1.jpeg")
    let imageView: UIImageView = {
          let img = UIImageView()
        if #available(iOS 13.0, *) {
            img.image = UIImage(systemName: "hare.fill")
        } else {
            // Fallback on earlier versions
        }
           img.contentMode = .scaleAspectFit
           img.translatesAutoresizingMaskIntoConstraints = false
           img.tintColor = .black
           return img
       }()

       let startSegmentationButton : UIButton = {
           let btn = UIButton(type: .system)
           btn.addTarget(self, action: #selector(handleStartSegmentationButton), for: .touchUpInside)
           btn.translatesAutoresizingMaskIntoConstraints = false
           btn.backgroundColor = .gray
           btn.layer.cornerRadius = 5
           btn.tintColor = .white
           btn.layer.masksToBounds  = true
           btn.setTitle("Begin", for: .normal)
           btn.isHidden = true
           return btn
       }()
    var imageSegmentationModel = DeepLabV3()
    var request :  VNCoreMLRequest?
    var originalImage:UIImage?
    var maskImage: UIImage?
    var originMaskImage: UIImage?
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        view.backgroundColor = .white
        let cameraBarButton = UIBarButtonItem(image: UIImage(systemName: "camera.circle.fill"),style: .done, target: self, action: #selector(handleCameraButtonTapped))
        let photoGalleryButton = UIBarButtonItem(image: UIImage(systemName: "photo.on.rectangle"), style: .done, target: self, action: #selector(handlePhotoGalleryTapped))
        self.navigationItem.rightBarButtonItems = [cameraBarButton,photoGalleryButton]
        self.title = titleText
        setupViews()
        layoutViews()
       setUpModel()
    }
    func setupViews() {
        view.addSubview(imageView)
        view.addSubview(startSegmentationButton)
//        test()
    }
    
    func layoutViews() {
        
        imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        imageView.heightAnchor.constraint(equalToConstant: 400).isActive = true
        imageView.widthAnchor.constraint(equalToConstant: 400).isActive = true
        
        startSegmentationButton.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 250).isActive = true
        startSegmentationButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40).isActive = true
        startSegmentationButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40).isActive = true
        startSegmentationButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
        
    }
    @objc func handlePhotoGalleryTapped() {
           showImagePickerController(sourceType: .photoLibrary)
   }

   @objc func handleCameraButtonTapped() {
     print("Camera Button Tapped")
     showImagePickerController(sourceType: .camera)
   }

   @objc func handleStartSegmentationButton() {
     self.startSegmentationButton.setTitle("In Progress...", for: .normal)
     guard (self.originalImage != nil) else { return }
     self.predict()
   }
    func showImagePickerController(sourceType: UIImagePickerController.SourceType) {
            if(UIImagePickerController.isSourceTypeAvailable(sourceType)){
                let imagePicker = UIImagePickerController()
                imagePicker.delegate = self
                imagePicker.sourceType = sourceType
                self.present(imagePicker, animated: true, completion: nil)
            }
            self.startSegmentationButton.isHidden = true
            self.startSegmentationButton.setTitle("Begin", for: .normal)
       }
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let image = info[.originalImage] as? UIImage{
                print("picked")
                self.imageView.image = image
                self.startSegmentationButton.isHidden = false
                self.originalImage = image.fixOrientation()!
                dismiss(animated: true, completion: nil)
            }
       }
    func setUpModel() {
            if let visionModel = try? VNCoreMLModel(for: imageSegmentationModel.model) {
                    request = VNCoreMLRequest(model: visionModel, completionHandler: visionRequestDidComplete)
                    request?.imageCropAndScaleOption = .scaleFill
            }
            else {
                    fatalError()
            }
    }
    func predict() {
            DispatchQueue.global(qos: .userInitiated).async {
                guard let request = self.request else { fatalError() }
                let handler = VNImageRequestHandler(cgImage: (self.originalImage?.cgImage)!, options: [:])
                do {
                    try handler.perform([request])
                }catch {
                    print(error)
                }
            }
       }
    func visionRequestDidComplete(request: VNRequest, error: Error?) {
            DispatchQueue.main.async {
                if let observations = request.results as? [VNCoreMLFeatureValueObservation],
                    let segmentationmap = observations.first?.featureValue.multiArrayValue {
                    print(segmentationmap.shape)
                    self.maskImage = segmentationmap.image(min: 0, max: 255)
                    self.maskImage = self.maskImage?.resizedImage(for: self.originalImage!.size)
                    self.originMaskImage = self.maskImage

//                    let op = OpenCVWra pper()
//                    self.maskImage = op.testC(self.maskImage!)
//                    if let image:UIImage = self.maskOriginalImage(){
//                        print("Success")
//                        self.imageView.image = image
//                    }
                    self.startSegmentationButton.setTitle("Done", for: .normal)
                    self.maskImage =  self.maskOriginalImage()
                    let  imageData = self.maskImage!.pngData();     // get png representation
                    let img = UIImage(data: imageData!)
//                    UIImageWriteToSavedPhotosAlbum(img!, nil, nil, nil)
                    self.maskImage = img
                    self.pickedDone()
                }
            }
                
        }
    func maskOriginalImage() -> UIImage? {
            if(self.maskImage != nil && self.originalImage != nil){
                let maskReference = self.maskImage?.cgImage!
                let imageMask = CGImage(maskWidth: maskReference!.width,
                                        height: maskReference!.height,
                                        bitsPerComponent: maskReference!.bitsPerComponent,
                                        bitsPerPixel: maskReference!.bitsPerPixel,
                                        bytesPerRow: maskReference!.bytesPerRow,
                                        provider: maskReference!.dataProvider!, decode: nil, shouldInterpolate: true)
                
//                let maskedReference = self.originalImage?.cgImage!.masking(imageMask!)
                
                return UIImage(cgImage: imageMask!)
                
            }else{
                return nil

            }
        }
    func pickedDone(){
        
    }
    
    func maskImageView(origin: UIImage, mask: UIImage) -> UIImage? {
            guard let source = origin.gaussianFilter(10)
            else {
                return nil
            }
            let size = origin.size
            UIGraphicsBeginImageContextWithOptions(size, false, 0)
            origin.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
            mask.draw(in: CGRect(origin: .zero, size: size), blendMode: .destinationIn, alpha: 1)
            let result = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            UIGraphicsBeginImageContextWithOptions(size, true, 0)
            source.draw(in: CGRect(x: -30, y: -30, width: size.width + 60, height: size.height + 60))
            result?.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
            let result1 = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return result1
        }
    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */
    

}



extension UIImage {
    // MARK: 马赛克样式

    func mosaicFilter(_ inputScale: CGFloat) -> UIImage? {
        return applyFilterTo(image: self, filterEffect: Filter(filterName: "CIPixellate", filterEffectValue: inputScale, filterEffectValueName: kCIInputScaleKey))
    }

    //        let lastImage = applyFilterTo(image: self.imageView!.image!, filterEffect: Filter(filterName: "CIGaussianBlur", filterEffectValue: 8.0, filterEffectValueName: kCIInputRadiusKey))

    // MARK: 高斯模糊

    func gaussianFilter(_ radius: CGFloat) -> UIImage? {
        return applyFilterTo(image: self, filterEffect: Filter(filterName: "CIGaussianBlur", filterEffectValue: radius, filterEffectValueName: kCIInputRadiusKey))
    }
    
    func applyFilterTo(image: UIImage, filterEffect: Filter) -> UIImage? {
        guard let cgImage = image.cgImage else {
            return nil
        }
       
        let ciImage = CIImage(cgImage: cgImage)
        let filter = CIFilter(name: filterEffect.filterName)
       
        filter?.setValue(ciImage, forKey: kCIInputImageKey)
       
        if let filterEffectValue = filterEffect.filterEffectValue,
           let filterEffectValueName = filterEffect.filterEffectValueName
        {
            filter?.setValue(filterEffectValue, forKey: filterEffectValueName)
        }
       
        var filteredImage: UIImage?
       
        if let output = filter?.outputImage {
            filteredImage = UIImage(ciImage: output)
        }
        return filteredImage
    }
}

struct Filter {
    let filterName: String
    var filterEffectValue: Any?
    var filterEffectValueName: String?
    
    init(filterName: String, filterEffectValue: Any?, filterEffectValueName: String?) {
        self.filterName = filterName
        self.filterEffectValue = filterEffectValue
        self.filterEffectValueName = filterEffectValueName
    }
}
